package com.jsy.mini12306.manage;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.jsy.mini12306.common.entity.*;
import com.jsy.mini12306.common.util.StringToLocalDateTimeUtil;
import com.jsy.mini12306.manage.bo.TrainBO;
import com.jsy.mini12306.manage.mapper.TrainCalendarMapper;
import com.jsy.mini12306.manage.mapper.TrainSeatMapper;
import com.jsy.mini12306.manage.mapper.TrainStationSeatStatusMapper;
import com.jsy.mini12306.manage.service.*;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;

/**
 * @author: SongyangJi
 * @description:
 * @since: 2021/9/3
 */

@SpringBootTest
public class GenerateDataForDev {

    @Resource
    StationService stationService;

    @Resource
    TrainPassStationService trainPassStationService;

    @Resource
    ManageTrainService manageTrainService;

    @Resource
    TrainSeatMapper trainSeatMapper;

    @Resource
    TrainStationSeatStatusMapper stationSeatStatusMapper;

    @Resource
    TrainCalendarService calendarService;


    TrainType[] trainTypes = TrainType.values();

    List<String> cities;


    // 车站数大于6的城市
    @Test
    void selectLargeCities() {
        List<Map<String, Object>> maps = stationService.getBaseMapper().selectMaps(
                new QueryWrapper<Station>().select("city").groupBy("city").having("count(city)>6"));
        List<String> arrayList = new ArrayList<>();
        maps.forEach(stringObjectMap ->
                arrayList.add((String) stringObjectMap.get("city"))
        );
        cities = arrayList;
        // 生成 json 数组
//        System.out.println("[");
//        for (String city : cities) {
//            System.out.println("'"+city+"', ");
//        }
//        System.out.println("]");
    }


    List<TrainBO> getTrainBOs() {

        List<TrainBO> trainBOS = new ArrayList<>();

        Map<String, List<Station>> cityStationsMap = new HashMap<>();
        for (String city : cities) {
            cityStationsMap.put(city, stationService.queryStationsByCity(city));
        }


        int MAX = 3000;

        int trainNameIdx = 2001;

        Random random = new Random();

        for (int cnt = 0; cnt < MAX; cnt++) {


            // 生成 TrainName
            TrainType trainType = trainTypes[random.nextInt(trainTypes.length)];
            String trainName = trainType.toString() + "" + (trainNameIdx++);
            int trainPatternId = random.nextInt(2) + 1;
            double distance = random.nextInt(1000) + 500;


            int stationNum = random.nextInt(20) + 5;
            ArrayList<Station> tempStations = new ArrayList<>();
            for (int idx = 0; idx < stationNum; idx++) {
                List<Station> stations = cityStationsMap.get(cities.get(idx));
                Station station = stations.get(random.nextInt(stations.size()));
                tempStations.add(station);
            }
            String startStationName = tempStations.get(0).getStationName();
            String endStationName = tempStations.get(tempStations.size() - 1).getStationName();

            String manager = tempStations.get(random.nextInt(tempStations.size())).getCity() + "局";


            // 生成Train
            Train train = Train.builder()
                    .trainName(trainName)
                    .trainPatternId(trainPatternId)
                    .distance(distance)
                    .type(trainType)
                    .manager(manager)
                    .startStationName(startStationName)
                    .endStationName(endStationName)
                    .build();

//            trainService.save(train);

            // 生成 List<TrainPassStation>
            List<TrainPassStation> trainPassStations = new ArrayList<>();
            int gap_day = 0;
            int runTime = 0;
            int stayTime = 0;
            LocalTime base = StringToLocalDateTimeUtil.convertStringToLocalTimeWithTimePattern("06:00:00");
            LocalTime pre = null;
            for (int j = 0; j < tempStations.size(); j++) {
                LocalTime arrivalTime = null, departTime = null;
                // 第一个
                if (j == 0) {
                    arrivalTime = departTime = base.plusMinutes(random.nextInt(60));

                } else if (j == tempStations.size() - 1) {
                    runTime = random.nextInt(90);
                    arrivalTime = departTime = pre.plusMinutes(runTime);

                } else {
                    runTime = random.nextInt(90);
                    arrivalTime = pre.plusMinutes(runTime);
                    stayTime = random.nextInt(10);
                    departTime = arrivalTime.plusMinutes(stayTime);

                }
                // 跨天
                if (pre != null && arrivalTime.isBefore(pre)) {
                    gap_day++;
                }
                pre = departTime;
                TrainPassStation trainPassStation = TrainPassStation.builder()
                        .stationId(tempStations.get(j).getStationId())
                        .sequence(j + 1) // 从1开始
                        .arrivalTime(arrivalTime)
                        .departTime(departTime)
                        .day(gap_day)
                        .build();
                trainPassStations.add(trainPassStation);
            }

            // 生成 List<TrainSeat> trainSeats;
            List<TrainSeat> seatList = new ArrayList<>();
            if (random.nextBoolean()) {
                seatList.add(new TrainSeat(null, SeatType.BUSINESS, 72));
                seatList.add(new TrainSeat(null, SeatType.FIRST, 240));
                seatList.add(new TrainSeat(null, SeatType.SECOND, 800));
            } else {
                seatList.add(new TrainSeat(null, SeatType.BUSINESS, 36));
                seatList.add(new TrainSeat(null, SeatType.FIRST, 120));
                seatList.add(new TrainSeat(null, SeatType.SECOND, 400));
            }

            List<TrainCalendar> calendars = new ArrayList<>();
            LocalDate today = LocalDate.parse("2021-09-07");

            if (random.nextBoolean()) {
                for (int k = 0; k < 30; k++) {
                    LocalDate date = today.plusDays(k);
                    calendars.add(new TrainCalendar(null, date));
                }
            } else {
                for (int i = 0; i < 30; i++) {
                    LocalDate date = today.plusDays(i);
                    if (random.nextBoolean()) {
                        calendars.add(new TrainCalendar(null, date));
                    }
                }

            }

            List<Ticket> tickets = new ArrayList<>();

            SeatType[] seatTypes = {SeatType.BUSINESS, SeatType.FIRST, SeatType.SECOND};
            double[] factors = {1.0, 0.7, 0.5};
            for (int idx = 0; idx < seatTypes.length; idx++) {
                int len = trainPassStations.size();
                // 循环
                for (int i = 0; i < len; i++) {
                    int prePrice = 0;
                    for (int j = i + 1; j < len; j++) {
                        TrainPassStation trainPassStation1 = trainPassStations.get(i);
                        TrainPassStation trainPassStation2 = trainPassStations.get(j);
                        SeatType seatType = seatTypes[idx];
                        double factor = factors[idx];
                        int price = (int) (factor * (random.nextInt(800) + 200));
                        price = Math.max(prePrice, price);
                        Ticket ticket = new Ticket(null, seatType, trainPassStation1.getStationId(), trainPassStation2.getStationId(), (float) price);
                        tickets.add(ticket);
                    }
                }
            }
            Collections.shuffle(cities);

            TrainBO trainBO = new TrainBO(train, trainPassStations, tickets, seatList, calendars);
//            test(trainBO);
//            manageTrainService.addTrainBO(trainBO);
            trainBOS.add(trainBO);

        }
        return trainBOS;
    }


    void test(TrainBO trainBO) {
        System.out.println(trainBO.getTrain());
        trainBO.getTrainSeats().forEach(System.out::println);
        System.out.println();
        trainBO.getTrainCalendars().forEach(System.out::println);
        System.out.println(trainBO.getTrainPassStations().size());
        trainBO.getTrainPassStations().forEach(System.out::println);
        System.out.println(trainBO.getTickets().size());
        trainBO.getTickets().forEach(System.out::println);
    }

    // 生成路径数据
    @Test
    void main() {
        selectLargeCities();
        List<TrainBO> trainBOs = getTrainBOs();
        for (TrainBO trainBO : trainBOs) {
            manageTrainService.addTrainBO(trainBO);
        }
    }


    // 检票口
    @Test
    void updateTicketGate() {
        Random random = new Random();
        String[] as = {"A", "B", "C", "D"};
        List<TrainPassStation> list = trainPassStationService.list();
        list.forEach(station -> {
            String s = as[random.nextInt(as.length)] + (random.nextInt(9) + 1);
            String s2 = "";
            if (random.nextBoolean()) {
                s2 = as[random.nextInt(as.length)] + (random.nextInt(9) + 1);
            }
            station.setTicketGate(s + s2);
            trainPassStationService.update(station, new UpdateWrapper<TrainPassStation>()
                    .eq("train_id", station.getTrainId()).eq("station_id", station.getStationId()).eq("sequence", station.getSequence()));
        });
    }

    // 生成 站次-座位-位图
    @Test
    void generateTrainStationSeatStatus() {
        int x = 1;
        List<TrainPassStation> trainPassStationList = trainPassStationService.list();
        for (TrainPassStation trainPassStation : trainPassStationList) {
            Integer trainId = trainPassStation.getTrainId();
            Integer stationId = trainPassStation.getStationId();

            List<LocalDate> localDates = calendarService.queryWorkingDatesOfTrain(trainId);

            for (LocalDate localDate : localDates) {
                List<TrainSeat> seatList = trainSeatMapper.selectList(new QueryWrapper<TrainSeat>().eq("train_id", trainId));
                for (TrainSeat trainSeat : seatList) {
                    int quantity = trainSeat.getQuantity();
                    SeatType type = trainSeat.getType();
                    TrainStationSeatStatus trainStationSeatStatus = new TrainStationSeatStatus(trainId, localDate, type, stationId, "0".repeat(quantity), 0L);
//                System.out.println(trainStationSeatStatus);
                    stationSeatStatusMapper.insert(trainStationSeatStatus);
                    x++;
                }
            }
        }
        System.out.println(x);
    }


}
